﻿namespace MicroCloud.Entity
{
    /// <summary>
    /// EF Core 作业单元
    /// <para>管理单元操作内涉及的所有上下文对象及其事务</para>
    /// </summary>
    public interface IUnitOfWork : IDisposable
    {
        #region 属性
        /// <summary>
        /// 获取 是否已提交
        /// </summary>
        bool HasCommitted { get; }

        /// <summary>
        /// 获取 是否启用事务
        /// </summary>
        bool IsEnabledTransaction { get; }

        #endregion

        #region "方法"
        /// <summary>
        /// 获取指定实体所属的数据上下文实例
        /// </summary>
        /// <typeparam name="TEntity">实体类型</typeparam>
        /// <typeparam name="TKey">实体主键类型</typeparam>
        /// <returns><typeparamref name="TEntity"/> 所属的数据上下文实例</returns>
        IDbContext GetEntityDbContext<TEntity, TKey>() where TEntity : IEntity<TKey>;

        /// <summary>
        /// 获取指定实体类型所属的数据上下文实例
        /// </summary>
        /// <param name="entityType">实体类型</param>
        /// <returns>实体所属的数据上下文实例</returns>
        IDbContext GetEntityDbContext(Type entityType);

        #region "获取指定类型的数据上下文实例"
        /// <summary>
        /// 获取指定类型的数据上下文实例
        /// </summary>
        /// <param name="dbContextType">数据上下文类型</param>
        /// <returns>数据上下文实例</returns>
        IDbContext GetDbContext(Type dbContextType);
        #endregion
        #region "获取指定类型的数据上下文实例集合"
        /// <summary>
        /// 获取指定类型的数据上下文实例集合
        /// </summary>
        /// <param name="dbContextTypes">上下文类型集合</param>
        /// <returns>数据上下文实例集合</returns>
        IDbContext[] GetDbContexts(params Type[] dbContextTypes);
        #endregion
        #region "获取所有的数据上下文实例集合"
        /// <summary>
        /// 获取所有的数据上下文实例集合
        /// </summary>
        /// <returns>数据上下文实例集合</returns>
        IDbContext[] GetAllDbContexts();
        #endregion


        #region "启用事务，事务代码写在 UnitOfWork.EnableTransaction() 与 UnitOfWork.Commit() 之间"
        /// <summary>
        /// 启用事务
        /// <para>事务代码写在 UnitOfWork.EnableTransaction() 与 UnitOfWork.Commit() 之间</para>
        /// </summary>
        void EnableTransaction();
        #endregion
        #region "开启或应用所有数据上下文的事务"
        /// <summary>
        /// 开启或应用所有数据上下文的事务
        /// <para>对数据库连接开启事务或应用现有同连接对象的数据上下文事务</para>
        /// </summary>
        /// <param name="isolationLevel">事务隔离级别</param>
        void BeginOrUseTransaction(IsolationLevel? isolationLevel = null);
        #endregion
        #region "开启或应用指定数据上下文的事务"
        /// <summary>
        /// 开启或应用指定数据上下文的事务
        /// <para>对数据库连接开启事务或应用现有同连接对象的数据上下文事务</para>
        /// </summary>
        /// <param name="context">数据上下文</param>
        /// <param name="isolationLevel">事务隔离级别</param>
        void BeginOrUseTransaction(IDbContext context, IsolationLevel? isolationLevel = null);
        #endregion
        #region "提交事务"
        /// <summary>
        /// 提交事务
        /// </summary>
        void Commit();
        #endregion
        #region "回滚事务"
        /// <summary>
        /// 回滚事务
        /// </summary>
        void Rollback();
        #endregion

        #region "异步开启或应用所有数据上下文的事务"
        /// <summary>
        /// 异步开启或应用所有数据上下文的事务
        /// <para>异步对数据库连接开启事务或应用现有同连接对象的数据上下文事务</para>
        /// </summary>
        /// <param name="isolationLevel">事务隔离级别</param>
        /// <param name="cancellationToken">异步取消标记</param>
        /// <returns></returns>
        Task BeginOrUseTransactionAsync(IsolationLevel? isolationLevel = null, CancellationToken cancellationToken = default);
        #endregion
        #region "异步开启或应用指定数据上下文的事务"
        /// <summary>
        /// 异步开启或应用指定数据上下文的事务
        /// <para>异步对数据库连接开启事务或应用现有同连接对象的数据上下文事务</para>
        /// </summary>
        /// <param name="context">数据上下文</param>
        /// <param name="isolationLevel">事务隔离级别</param>
        /// <param name="cancellationToken">异步取消标记</param>
        /// <returns></returns>
        Task BeginOrUseTransactionAsync(IDbContext context, IsolationLevel? isolationLevel = null, CancellationToken cancellationToken = default);
        #endregion
        #region "异步提交事务"
        /// <summary>
        /// 异步提交事务
        /// </summary>
        /// <param name="cancellationToken">异步取消标记</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        Task CommitAsync(CancellationToken cancellationToken = default);
        #endregion
        #region "异步回滚事务"
        /// <summary>
        /// 异步回滚事务
        /// </summary>
        /// <param name="cancellationToken">异步取消标记</param>
        /// <returns></returns>
        Task RollbackAsync(CancellationToken cancellationToken = default);
        #endregion

        #endregion

    }
}
